#pragma once

#include <iostream>
#include <string>
#include <functional>
#include <sys/types.h>
#include <sys/socket.h>
#include <vector>
#include <pthread.h>
#include "InetAddr.hpp"
#include "ThreadPool.hpp"
#include "LockGuard.hpp"

// class user//用户类
// {
//     public:
//     private:
// };

using task_t = std::function<void()>;

class Route
{
public:
    Route() 
    {
        pthread_mutex_init(&_mutex,nullptr);
    }
    void CheckOnlineUser(InetAddr &who)
    {
        LockGuard lockguard(&_mutex);
        for (auto &user : _online_user)
        {
            if (user == who)
            {
                LOG(DEBUG, "%s is exists\n",user.AddrStr().c_str());
                return; // 存在
            }
        }
        LOG(DEBUG, "%s is not exists,add it\n",who.AddrStr().c_str());
        _online_user.push_back(who); // 不存在
    }
    void Offline(InetAddr &who)
    {
        LockGuard lockguard(&_mutex);

        auto iter = _online_user.begin();
        for (; iter != _online_user.end(); iter++)
        {
            if (*iter == who)
            {
                LOG(DEBUG,"%s is offline\n",who.AddrStr().c_str());

                _online_user.erase(iter);

                break;
            }
        }
    }
    void ForwardHelper(int sockfd, const std::string message, InetAddr who) // 把message通过sockfd转发给所有人
    {
        LockGuard lockguard(&_mutex);

        std::string send_message="["+who.AddrStr()+"]#"+message;
        for (auto &user : _online_user)
        {
            struct sockaddr_in peer = user.Addr();
                LOG(DEBUG, "Forward message to %s, message = %s\n",user.AddrStr().c_str(),send_message.c_str());

            ::sendto(sockfd, send_message.c_str(), send_message.size(), 0, (struct sockaddr *)&peer, sizeof peer); // 转发给所有人
        }
    }
    void Forward(int sockfd, const std::string &message, InetAddr &who) // 转发 从who收message，发给sockfd
    {
        // 1.保证该用户在线 如果在，什么都不做 如果不在，自动添加到 _online_user
        CheckOnlineUser(who); // 检查who是否在 _online_user中

        // 1.1 message=="QUIT""Q"-->退出
        if (message == "QUIT" || message == "Q")
        {
            Offline(who); // 下线
        }
        // 2.保证who一定在_online_user中
        // ForwardHelper(sockfd,message);
        task_t t = std::bind(&Route::ForwardHelper, this, sockfd, message, who);
        ThreadPool<task_t>::GetInstance()->Equeue(t);
    }
    ~Route() 
    {
        pthread_mutex_unlock(&_mutex);
    }

private:
    std::vector<InetAddr> _online_user; // 用变长数组来存储在线用户列表
    pthread_mutex_t _mutex;
};